/**
 * 
 */
package com.yishuki.bluewhale.util;

import java.io.File;
import java.io.IOException;
import java.util.Date;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.yishuki.bluewhale.Constant;
import com.yishuki.bluewhale.UserType;
import com.yishuki.bluewhale.db.access.DBUtil;
import com.yishuki.bluewhale.db.entity.Category;
import com.yishuki.bluewhale.db.entity.User;

import name.yzhu.common.EnvVariable;
import name.yzhu.common.conf.PropertyConfig;
import name.yzhu.common.lang.LangUtil;
import name.yzhu.common.util.Security;
import name.yzhu.database.DataBaseException;
import name.yzhu.database.IDbUtil;

/**
 * The generic function for bluewhale
 * @author yhzhu
 *
 */
public class YishukiSystem {
	private static final Log LOG = LogFactory.getLog(YishukiSystem.class);
	/**
	 * initialize yishuki system <br>
	 * <b>Note:</b> this method is called ONLY ONE time when system is deployed
	 * @throws DataBaseException
	 */
    public void initialSystem() {
    	EnvVariable.initialGlobalEnvVariable();
    	PropertyConfig cfg = new PropertyConfig() ;
    	try {
			cfg.load(new File(EnvVariable.getWorkingDirectory(), 
					Constant.PROJECT_PROPERTIES));
			
			initialDB(cfg);
			
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}
		
    }

	private void initialDB(PropertyConfig cfg) throws IOException  {
		IDbUtil db = null;
		try {
			DBUtil.initialDatabase(cfg);
			db = DBUtil.getDbUtil();

			String sql = "insert into tbl_permission(PERMISSION_ID, NAME, PERMISSION_MASK) values(?,?,?)";
			UserType[] uts = UserType.values();
			String params[] = new String[uts.length * 3];
			int paramCount = 0;
			params[paramCount++] = String.valueOf(uts[0].getId());
			params[paramCount++] = String.valueOf(uts[0].getName());
			params[paramCount++] = String.valueOf(uts[0].getMask());
			for (int i=1; i<uts.length; i++){
				sql += ", (?,?,?)";
				params[paramCount++] = String.valueOf(uts[i].getId());
				params[paramCount++] = String.valueOf(uts[i].getName());
				params[paramCount++] = String.valueOf(uts[i].getMask());
			}
			LOG.debug("permission sql: "+sql+"  params: "+LangUtil.ObjectArrayToString(params));
			db.executeNativeSQL(sql, params);
			
			sql = "insert into tbl_user(user_id, user_name, password, email, PERMISSION_ID, SIGN_UP_TIME) " +
					"values(?,?,?,?,?,?)";
			db.executeNativeSQL(sql, String.valueOf(Constant.USER_ADMIN_ID), "admin", Security.EncodeByMD5("admin"), Constant.USER_ADMIN_EMAIL,
					String.valueOf(Constant.PERMISSION_ADMIN_ID), 
					name.yzhu.common.Constant.TIMESTAMP_FORMAT.format(new Date()));
			
			sql = "insert into tbl_category(CATEGORY_ID, NAME, DESCRIPTION, PARENT_ID) values(?,?,?,?)";
			db.executeNativeSQL(sql, String.valueOf(Constant.CATEGORY_ROOT_ID), 
					"root", "root category, others are its descendants", "-1");
			
			db.flush();
		} catch (DataBaseException e) {
			if (db != null)
				db.rollback();
			if (LOG.isDebugEnabled())
				LOG.debug(e.getMessage(), e);
			throw new IOException(e);
		}
		finally{
			if (db != null)
			    db.close();
		}
		
		
	}
	/**
	 * clear all of data from system <br>
	 * <b>you have to be very carefully when you call this method</b>
	 */
	public void clearSystem(){
		EnvVariable.initialGlobalEnvVariable();
    	PropertyConfig cfg = new PropertyConfig() ;
    	try {
			cfg.load(new File(EnvVariable.getWorkingDirectory(), 
					Constant.PROJECT_PROPERTIES));
			
			clearDB(cfg);
			
		} catch (IOException e) {
			LOG.error(e.getMessage(), e);
		}
		
	}

	private void clearDB(PropertyConfig cfg) throws IOException {
		IDbUtil db = null;
		try {
			DBUtil.initialDatabase(cfg);
			db = DBUtil.getDbUtil();
			
			Category root = db.getForObejct(Category.class, Constant.CATEGORY_ROOT_ID);
			db.Delete(root);
			
			User admin = db.getForObejct(User.class, Constant.USER_ADMIN_ID);
			db.Delete(admin);
			
//			Permission p = db.getForObejct(Permission.class, Constant.PERMISSION_ADMIN_ID);
//			db.Delete(p);
			String sql = "delete from TBL_PERMISSION ";
			db.executeNativeSQL(sql);
			
			db.close();
		} catch (DataBaseException e) {
			if (db != null)
				db.rollback();
			
			if (LOG.isDebugEnabled())
				LOG.debug(e.getMessage(), e);
			throw new IOException(e);
		}
		finally {
			if (db != null)
				db.close();
		}
	}
	
	public static void main(String[] args) {
		YishukiSystem system = new YishukiSystem();
		if (args != null && args.length > 0 && 
				args[0].equalsIgnoreCase("clear") )
		    system.clearSystem();
		else 
			system.initialSystem();
	}
}
